package com.atguigu.gulimall.product.service.impl;
import com.atguigu.common.constant.ProductConstant;
import com.atguigu.gulimall.product.dao.AttrAttrgroupRelationDao;
import com.atguigu.gulimall.product.dao.AttrGroupDao;
import com.atguigu.gulimall.product.dao.CategoryDao;
import com.atguigu.gulimall.product.entity.AttrAttrgroupRelationEntity;
import com.atguigu.gulimall.product.entity.AttrEntity;
import com.atguigu.gulimall.product.entity.AttrGroupEntity;
import com.atguigu.gulimall.product.entity.CategoryEntity;
import com.atguigu.gulimall.product.vo.AttrEntityVo;
import com.atguigu.gulimall.product.vo.AttrResVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.*;
import java.util.stream.Collectors;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.atguigu.common.utils.PageUtils;
import com.atguigu.common.utils.Query;
import com.atguigu.gulimall.product.dao.AttrDao;
import com.atguigu.gulimall.product.service.AttrService;
import org.springframework.transaction.annotation.Transactional;
@Service("attrService")
public class AttrServiceImpl extends ServiceImpl<AttrDao, AttrEntity> implements AttrService {
    @Autowired
    private AttrAttrgroupRelationDao dao;
    @Autowired
    private CategoryDao categoryDao;
    @Autowired
    private AttrGroupDao attrGroupDao;


    @Override
    public List<AttrEntity> getRelationAttrByGroupId(Long attrgroupId) {
        //如何你该分组下没关联属性，这个entities长度为0
        List<AttrAttrgroupRelationEntity> entities = dao.selectList(new QueryWrapper<AttrAttrgroupRelationEntity>().eq("attr_group_id", attrgroupId));
        //这个entities长度为0,那么attrIds也为0,但不为空
        List<Long> attrIds = entities.stream().map((attr) -> {
            return attr.getAttrId();
        }).collect(Collectors.toList());

        if(attrIds == null || attrIds.size() == 0){
            return null;
        }
        Collection<AttrEntity> attrEntities = this.listByIds(attrIds);
        return (List<AttrEntity>) attrEntities;
    }

    /**
     * 通过ids获取能够搜索的属性
     * @param baseAttrIds
     * @return
     */
    @Override
    public List<AttrEntity> getAttrsOfSearchTpye(List<Long> baseAttrIds,Long type) {
        return baseMapper.selectList(new LambdaQueryWrapper<AttrEntity>()
                 .eq(AttrEntity::getSearchType,type)
                 .in(AttrEntity::getAttrId,baseAttrIds));
    }

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<com.atguigu.gulimall.product.entity.AttrEntity> page = this.page(
                new Query<com.atguigu.gulimall.product.entity.AttrEntity>().getPage(params),
                new QueryWrapper<com.atguigu.gulimall.product.entity.AttrEntity>()
        );
        return new PageUtils(page);
    }

    @Override
    @Transactional
    public void saveAtrr(AttrEntityVo attr) {
        com.atguigu.gulimall.product.entity.AttrEntity attrEntity = new com.atguigu.gulimall.product.entity.AttrEntity();
        BeanUtils.copyProperties(attr, attrEntity);
        //保存基本数据 主键会回填
        this.save(attrEntity);
        //保存关联关系,但是因为销售属性在本项目的设计中不归属一个具体分组，所以不许建立分组和属性的关系
        if (attrEntity.getAttrType()==ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode()){
            AttrAttrgroupRelationEntity attrAttrgroupRelationEntity = new AttrAttrgroupRelationEntity();
            attrAttrgroupRelationEntity.setAttrId(attrEntity.getAttrId());
            attrAttrgroupRelationEntity.setAttrGroupId(attr.getAttrGroupId());
            dao.insert(attrAttrgroupRelationEntity);
        }
//        AttrAttrgroupRelationEntity attrAttrgroupRelationEntity = new AttrAttrgroupRelationEntity();
//        attrAttrgroupRelationEntity.setAttrId(attrEntity.getAttrId());
//        attrAttrgroupRelationEntity.setAttrGroupId(attr.getAttrGroupId());
//        dao.insert(attrAttrgroupRelationEntity);
    }

    /**
     * 拿分类下的属性
     *
     * @param params
     * @param catelogId
     * @return
     */
    @Override
    public PageUtils queryPageByCatelogId(Map<String, Object> params, Long catelogId) {
        //不管分类id是不是0，我都需要有搜索的功能，要搜索，一个是根据组id搜 或者 通过组名模糊查询
        QueryWrapper<AttrEntity> queryWrapper = new QueryWrapper<>();
        String key = (String) params.get("key");
        if (StringUtils.isNotEmpty(key)) {
            queryWrapper.eq("attr_id", key).or().like("attr_name", key);
        }
        //意思就是说不具体查某个分类的属性，而是查所有属性，不过是进行分页和条件查询
        if (catelogId == ProductConstant.CategoryLevel.CATEGORY_LEVEL_ONE.getCode()) {
            //Query是你自己封装的
            Query<AttrEntity> query = new Query<>();
            //就是把map中接收到前端的分页数据封装到ipage里面
            IPage<AttrEntity> ipage = query.getPage(params);
            IPage<AttrEntity> page = this.page(ipage, queryWrapper);
            return new PageUtils(page);
        } else {
            //走这里的代码就证明，前端请求了具体分类下的分组
            queryWrapper.and((obj) -> {
                obj.eq("catelog_id", catelogId);
            });
            Query<AttrEntity> query = new Query<>();
            //就是把map中接收到前端的分页数据封装到ipage里面
            IPage<AttrEntity> ipage = query.getPage(params);
            IPage<AttrEntity> page = this.page(ipage, queryWrapper);
            PageUtils pageUtils = new PageUtils(page);
            //到这里pageUtils里面的list还是来自于page里面的page.getRecords()
            //当然这个Records()里面是AttrEntity的集合
            List<AttrEntity> attrEntityList = page.getRecords();
            List<AttrResVo> attrResVoList = attrEntityList.stream().map((attrEntity) -> {
                AttrResVo attrResVo = new AttrResVo();
                BeanUtils.copyProperties(attrEntity, attrResVo);
                CategoryEntity categoryEntity = categoryDao.selectById(attrEntity.getCatelogId());
                //设置分类的名字
                attrResVo.setCatelogName(categoryEntity.getName());
                LambdaQueryWrapper<AttrAttrgroupRelationEntity> wrapper = new LambdaQueryWrapper<>();
                wrapper.eq(AttrAttrgroupRelationEntity::getAttrId, attrEntity.getAttrId());
                AttrAttrgroupRelationEntity one = dao.selectOne(wrapper);
                AttrGroupEntity attrGroupEntity = attrGroupDao.selectById(one.getAttrGroupId());
                //设置分组的名字
                attrResVo.setGroupName(attrGroupEntity.getAttrGroupName());
                return attrResVo;
            }).collect(Collectors.toList());
            pageUtils.setList(attrResVoList);
            return pageUtils;
        }
    }

    /**
     * 拿分类下的属性方法v1版本
     *
     * @param params
     * @param catelogId
     * @param attrType
     * @return
     */
    @Override
    public PageUtils queryPageByCatelogIdV1(Map<String, Object> params, Long catelogId, String attrType) {
        //不管分类id是不是0，我都需要有搜索的功能，要搜索，一个是根据组id搜 或者 通过组名模糊查询
        QueryWrapper<AttrEntity> queryWrapper = new QueryWrapper<>();
        String key = (String) params.get("key");
        queryWrapper.eq("attr_type",attrType.equalsIgnoreCase("base")?
                ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode():ProductConstant.AttrEnum.ATTR_TYPE_SALE.getCode());
        if (StringUtils.isNotEmpty(key)) {
            queryWrapper.eq("attr_id", key).or().like("attr_name", key);
        }
        Query<AttrEntity> query = new Query<>();
        //就是把map中接收到前端的分页数据封装到ipage里面
        IPage<AttrEntity> ipage = query.getPage(params);
        //意思就是说不具体查某个分类的属性，而是查所有属性，不过是进行分页和条件查询
        //catelogId为0是不存在的，只不过，我们规定前端查所有分类，就带0
        if (catelogId == ProductConstant.CategoryLevel.CATEGORY_LEVEL_ONE.getCode()) {
            //Query是你自己封装的
            IPage<AttrEntity> page = this.page(ipage, queryWrapper);
            PageUtils pageUtils = new PageUtils(page);
            List<AttrResVo> attrResVoList = this.translateAttrEntityToAttrResVo(page.getRecords());
            pageUtils.setList(attrResVoList);
            return pageUtils;
        }else {
            //走这里的代码就证明，前端请求了具体分类下的分组
            queryWrapper.and((obj) -> {
                obj.eq("catelog_id", catelogId);
            });
            IPage<AttrEntity> page = this.page(ipage, queryWrapper);
            PageUtils pageUtils = new PageUtils(page);
            //到这里pageUtils里面的list还是来自于page里面的page.getRecords()
            //当然这个Records()里面是AttrEntity的集合
            List<AttrEntity> attrEntityList = page.getRecords();
            List<AttrResVo> attrResVoList = translateAttrEntityToAttrResVo(attrEntityList);
            pageUtils.setList(attrResVoList);
            return pageUtils;
        }
    }

    @Override
    public AttrResVo getAttrResVoByAttrId(Long attrId) {
        AttrEntity attrEntity = baseMapper.selectById(attrId);
        AttrResVo attrResVo = new AttrResVo();
        BeanUtils.copyProperties(attrEntity,attrResVo);
        //把分组id和组名给设置上,销售属性没有所属分组，这里要判断
        if (attrEntity.getAttrType()==ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode()){
            LambdaQueryWrapper<AttrAttrgroupRelationEntity> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(AttrAttrgroupRelationEntity::getAttrId,attrId);
            AttrAttrgroupRelationEntity one = dao.selectOne(wrapper);
            if (one.getAttrGroupId()!=null){
                attrResVo.setAttrGroupId(one.getAttrGroupId());
                AttrGroupEntity attrGroupEntity = attrGroupDao.selectById(one.getAttrGroupId());
                if (attrGroupEntity !=null){
                    attrResVo.setGroupName(attrGroupEntity.getAttrGroupName());
                }
            }
        }
        //把分类，父分类，祖父分类，的id设置上
        //这个集合的目的就是装分类，和上级分类的id
        List<Long> idList = new ArrayList<>();
        CategoryEntity categoryEntity = categoryDao.selectById(attrEntity.getCatelogId());
        List<Long> pathList = getCurrentCategoryPathV1(attrEntity.getCatelogId(), idList);
        Collections.reverse(pathList);
        Long[] ids = pathList.toArray(new Long[pathList.size()]);
        attrResVo.setCatelogPath(ids);
        attrResVo.setCatelogName(categoryEntity.getName());
        return attrResVo;
    }

    @Override
    @Transactional
    public void updateAttrDetail(AttrEntityVo attr) {
        //先更新本实体对应的表
        AttrEntity attrEntity = new AttrEntity();
        BeanUtils.copyProperties(attr,attrEntity);
        baseMapper.updateById(attrEntity);
        //如果你是个销售属性，你在pms_attr_attrgroup_relation表中也没有记录，所以你不需要更新该表
        if (attrEntity.getAttrType()==ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode()){
            //pms_attr_attrgroup_relation要更新该属性的分组id
            LambdaQueryWrapper<AttrAttrgroupRelationEntity> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(AttrAttrgroupRelationEntity::getAttrId, attr.getAttrId());
            AttrAttrgroupRelationEntity one = dao.selectOne(wrapper);
            //要新new一个模版
            AttrAttrgroupRelationEntity update = new AttrAttrgroupRelationEntity();
            //one是有可能为空的 前端录的时候，属性是可以暂时不要分组的
            if (one !=null){
                update.setId(one.getId());
                update.setAttrGroupId(attr.getAttrGroupId());
                dao.updateById(update);
            }
        }
    }

    /**
     *
     * @param currentCategory 当前分类
     * @param ids 分类id容器
     * @param categoryList 所有分类
     * @return
     */
    private List<Long>getCurrentCategoryPath(CategoryEntity currentCategory,List<Long> ids
            ,List<CategoryEntity> categoryList){
        //首先把当前分类id添加进去
        ids.add(currentCategory.getCatId());
        //当前分类的父分类id等于0,直接返回ids
        if (currentCategory.getParentCid()==ProductConstant.CategoryLevel.CATEGORY_LEVEL_ONE.getCode()){
            return ids;
        }
        List<CategoryEntity> parentCategoryList = categoryList.stream().filter((category) -> {
            return category.getCatId() == currentCategory.getParentCid();
        }).collect(Collectors.toList());
        CategoryEntity parentCategory = parentCategoryList.get(0);
        return getCurrentCategoryPath(parentCategory,ids,categoryList);
    }

    /**
     * v1版本不直接查出所有分类
     * @param currentCategoryId
     * @param ids
     * @return
     */
    private List<Long>getCurrentCategoryPathV1(Long currentCategoryId,List<Long> ids){
        ids.add(currentCategoryId);
        CategoryEntity currentCategory = categoryDao.selectById(currentCategoryId);
        if (currentCategory.getParentCid()==ProductConstant.CategoryLevel.CATEGORY_LEVEL_ONE.getCode()){
            return ids;
        }
        //表示没填父分类
        CategoryEntity parentCategory = categoryDao.selectById(currentCategory.getParentCid());
        if (parentCategory.getCatId() !=null){
            return getCurrentCategoryPathV1(parentCategory.getCatId(), ids);
        }
        return ids;
    }
    private List<AttrResVo> translateAttrEntityToAttrResVo(List<AttrEntity> attrEntityList) {
        List<AttrResVo> attrResVoList = attrEntityList.stream().map((attrEntity) -> {
            AttrResVo attrResVo = new AttrResVo();
            BeanUtils.copyProperties(attrEntity, attrResVo);
            CategoryEntity categoryEntity = categoryDao.selectById(attrEntity.getCatelogId());
            if (categoryEntity !=null){
                //设置分类的名字
                attrResVo.setCatelogName(categoryEntity.getName());
            }
            //因为销售属性，就没有分组，在分组属性表里面也没有记录，所以呢要不要给它设置分组名要判断
            if (attrEntity.getAttrType()==ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode()){
                LambdaQueryWrapper<AttrAttrgroupRelationEntity> wrapper = new LambdaQueryWrapper<>();
                wrapper.eq(AttrAttrgroupRelationEntity::getAttrId, attrEntity.getAttrId());
                AttrAttrgroupRelationEntity one = dao.selectOne(wrapper);
                if (one !=null){
                    AttrGroupEntity attrGroupEntity = attrGroupDao.selectById(one.getAttrGroupId());
                    if (attrGroupEntity !=null){
                        //设置分组的名字
                        attrResVo.setGroupName(attrGroupEntity.getAttrGroupName());
                    }
                }
            }
            return attrResVo;
        }).collect(Collectors.toList());
        return attrResVoList;
    }
}